Conversation
a74nh
commented
Apr 13, 2026
- Add PerfMapSymbolReader and GetInfoForMethod in System.Private.CoreLib to read PDB/embedded PDB sequence points for perfmap/jitdump.
- Retarget the native delegate creation to System.Diagnostics.StackTrace from SOS.NETCore
- Add JIT_CODE_DEBUG_INFO records using managed debug info, gated behind config variable
* Add PerfMapSymbolReader and GetInfoForMethod in System.Private.CoreLib to read PDB/embedded PDB sequence points for perfmap/jitdump. * Retarget the native delegate creation to System.Diagnostics.StackTrace from SOS.NETCore * Add JIT_CODE_DEBUG_INFO records using managed debug info, gated behind config variable
|
Tagging subscribers to this area: @agocke |
There was a problem hiding this comment.
Pull request overview
This PR adds source/line debug-info support to perfmap/jitdump by introducing a managed PDB sequence-point reader and wiring CoreCLR’s perfmap/jitdump pipeline to emit JIT_CODE_DEBUG_INFO records (gated by a new config knob).
Changes:
- Add
PerfMapSymbolReader(System.Diagnostics.StackTrace) to read sequence points from associated/embedded Portable PDBs for a given method token. - Retarget native delegate creation to
System.Diagnostics.StackTrace.GetInfoForMethodin System.Private.CoreLib and add re-entrancy guards. - Extend jitdump logging to optionally emit
JIT_CODE_DEBUG_INFOrecords and plumb debug-info payloads fromperfmap.cppintoPAL_PerfJitDump_LogMethod.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/PerfMapSymbolReader.cs | New managed helper to read sequence points from associated/embedded PDBs into a native buffer. |
| src/libraries/System.Diagnostics.StackTrace/src/System.Diagnostics.StackTrace.csproj | Include new source file in the StackTrace library build. |
| src/libraries/System.Diagnostics.StackTrace/src/ILLink/ILLink.Descriptors.LibraryBuild.xml | Preserve PerfMapSymbolReader for trimming scenarios. |
| src/coreclr/vm/perfmap.h | Add s_EmitDebugInfo toggle for debug-info emission. |
| src/coreclr/vm/perfmap.cpp | Build/emit serialized jitdump debug-info payload from managed sequence points when enabled. |
| src/coreclr/vm/gdbjithelpers.h | Update debug-info delegate signature to return int and take MethodDebugInfo*. |
| src/coreclr/vm/gdbjit.cpp | Add re-entrancy guard and update delegate invocation for new signature. |
| src/coreclr/pal/src/misc/perfjitdump.cpp | Add JIT_CODE_DEBUG_INFO record support and extend logging API to accept debug/unwind payloads + sizes. |
| src/coreclr/pal/inc/pal.h | Update PAL_PerfJitDump_LogMethod signature to include debug/unwind payload sizes and const pointers. |
| src/coreclr/inc/clrconfigvalues.h | Add PerfMapEmitDebugInfo config knob. |
| src/coreclr/dlls/mscoree/exports.cpp | Create the native delegate against System.Private.CoreLib / System.Diagnostics.StackTrace.GetInfoForMethod. |
src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/PerfMapSymbolReader.cs
Show resolved
Hide resolved
| /// <summary> | ||
| /// Populate a native buffer with sequence points for the specified method token using the assembly's associated or embedded PDB. | ||
| /// </summary> | ||
| /// <returns>true if at least one sequence point was written; otherwise false.</returns> | ||
| internal static bool GetInfoForMethod([MarshalAs(UnmanagedType.LPUTF8Str)] string assemblyPath, int methodToken, IntPtr points, int size) | ||
| { | ||
| if (string.IsNullOrEmpty(assemblyPath) || points == IntPtr.Zero || size <= 0) | ||
| { | ||
| return false; | ||
| } |
|
This PR is useful for any tool or developer that uses linux perf to analyse .NET applications. Specifically, support is being added for use by Arm Performix, with the aim of using this to help migrate users. Example output of perf annotate showing the line numbers from an example C# that was run through perf: This PR was entirely written by codex. I've spent some time testing and reviewing the code. It looks sensible and works for me, however I don't claim to be familiar with some of these areas of CoreCLR. |
|
Still need to add tests. But, taking this out of draft to get some comments to see if this is in the right direction |
There was a problem hiding this comment.
Pull request overview
This PR adds managed symbol-reading support to enrich perfmap/jitdump output with source/line information by reading Portable PDB sequence points, and wires the runtime to use this new managed helper when emitting perfmap/jitdump data.
Changes:
- Add
PerfMapSymbolReader(System.Diagnostics.StackTrace) and a CoreLibStackTrace.GetInfoForMethodunmanaged callback to retrieve sequence points from associated/embedded Portable PDBs. - Extend perfmap/jitdump plumbing to optionally emit
JIT_CODE_DEBUG_INFOrecords (gated byPerfMapEmitDebugInfo) and update PAL jitdump logging to accept a debug-info payload. - Retarget the runtime delegate creation from SOS to
System.Private.CoreLib/System.Diagnostics.StackTracefor debug-info retrieval.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/PerfMapSymbolReader.cs | New managed helper to read Portable PDB sequence points and fill a native buffer. |
| src/libraries/System.Diagnostics.StackTrace/src/System.Diagnostics.StackTrace.csproj | Includes the new PerfMapSymbolReader.cs in the build. |
| src/libraries/System.Diagnostics.StackTrace/src/ILLink/ILLink.Descriptors.LibraryBuild.xml | Preserves PerfMapSymbolReader for trimming scenarios. |
| src/coreclr/vm/perfmap.h | Adds s_EmitDebugInfo configuration flag. |
| src/coreclr/vm/perfmap.cpp | Emits optional jitdump debug-info payload and passes it to PAL jitdump logging. |
| src/coreclr/vm/gdbjithelpers.h | Updates the managed debug-info delegate signature to use a pointer and int return. |
| src/coreclr/vm/gdbjit.cpp | Adds re-entrancy guard and updates delegate invocation to new signature. |
| src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs | Adds unmanaged callback (GetInfoForMethod) and UnsafeAccessor bridge into System.Diagnostics.StackTrace. |
| src/coreclr/pal/src/misc/perfjitdump.cpp | Adds JIT_CODE_DEBUG_INFO record support and extends LogMethod parameters. |
| src/coreclr/pal/inc/pal.h | Updates PAL_PerfJitDump_LogMethod signature to include debug/unwind buffers + sizes. |
| src/coreclr/inc/clrconfigvalues.h | Adds PerfMapEmitDebugInfo config value. |
| src/coreclr/dlls/mscoree/exports.cpp | Retargets delegate creation to System.Diagnostics.StackTrace.GetInfoForMethod and enables it for FEATURE_PERFMAP too. |
src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs
Outdated
Show resolved
Hide resolved
src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/PerfMapSymbolReader.cs
Outdated
Show resolved
Hide resolved
|
@noahfalk, @brianrob, @steveisok, PTAL if it aligns with our diagnostics story. This change is related to the Performix tool supporting source annotation. |
There was a problem hiding this comment.
Pull request overview
This PR adds source/line mapping support for perfmap/jitdump by introducing a managed symbol reader (Portable PDB / embedded PDB) and wiring it into CoreCLR’s perfmap and jitdump emission paths on Unix.
Changes:
- Add
PerfMapSymbolReaderinSystem.Diagnostics.StackTraceand preserve it for trimming so CoreCLR can query Portable PDB sequence points. - Retarget the native debug-info delegate from
SOS.NETCoretoSystem.Private.CoreLib(System.Diagnostics.StackTrace.GetInfoForMethod) and adjust native delegate signatures/call sites. - Emit
JIT_CODE_DEBUG_INFOrecords into jitdump (gated by the newPerfMapEmitDebugInfoconfig).
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/PerfMapSymbolReader.cs | New managed reader to extract sequence points from associated/embedded Portable PDBs. |
| src/libraries/System.Diagnostics.StackTrace/src/System.Diagnostics.StackTrace.csproj | Includes the new PerfMapSymbolReader.cs in the build. |
| src/libraries/System.Diagnostics.StackTrace/src/ILLink/ILLink.Descriptors.LibraryBuild.xml | Ensures PerfMapSymbolReader is preserved under trimming. |
| src/coreclr/vm/perfmap.h | Adds s_EmitDebugInfo config flag. |
| src/coreclr/vm/perfmap.cpp | Generates and logs serialized jitdump debug-info payloads when enabled. |
| src/coreclr/vm/gdbjithelpers.h | Updates delegate signature to use pointer + int return. |
| src/coreclr/vm/gdbjit.cpp | Adds reentrancy guard and updates delegate usage; attempts to handle missing locals. |
| src/coreclr/pal/src/misc/perfjitdump.cpp | Extends jitdump logging to optionally write JIT_CODE_DEBUG_INFO records and adjusts API. |
| src/coreclr/pal/inc/pal.h | Updates PAL_PerfJitDump_LogMethod signature to include buffer + size pairs. |
| src/coreclr/inc/clrconfigvalues.h | Adds PerfMapEmitDebugInfo config value. |
| src/coreclr/dlls/mscoree/exports.cpp | Retargets delegate creation to CoreLib StackTrace method and widens feature guard. |
| src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs | Adds UnmanagedCallersOnly callback and UnsafeAccessor bridge to the library symbol reader. |
src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs
Outdated
Show resolved
Hide resolved
|
I'm hesitant that trying to do this source resolution at runtime will necessarily give the overall scenario characteristics you are looking for but we should discuss.
The alternative that I've seen other profilers do is PDB/source resolution as a post-processing step after the trace is collected rather than at runtime. It requires at runtime capturing IP->IL offset mappings, then later using PDBs to convert IL -> source line info. Its probably a bit more complex to create initially but gives a higher fidelity result and supports acquiring symbols out-of-band such as from a symbol server. A couple possibilities on how that could be built:
|
Thanks.
Even if we did this as a post processing step instead (or in any other conceivable way) then the source code would need to be present at the point of processing. This is all hidden behind an additional config variable (
Agreed, this would be a concern as we want this to effect performance as little as possible. This will overhead will happen at jit compilation time, not execution time. So mostly startup would be effected. Looking at my test app, running it under Linux perf, with Do you have an suggestions as to other ways to measure the impact? Or at what level you'd consider this to be too much?
Ok.
Post processing would be a valid way of doing this
That would have the same issue that it'd be during runtime and so would effect performance? |
Downside to this is you still have overhead. You remove all the PDB reading, but it still needs to write a similar amount of information out to the dump. In addition, using the PR as is, this will work out of the box for any Linux app which uses perf. Using IL in jitdump or events is a bespoke mechanism. We'd essentially have to write a tool/library that does all the processing, then that needs distributing and fitting into any app that wants this information. |
